﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace SeizyUtils.Common.Utilities
{
    /// <summary>
    /// ハンディで利用されるファイル・フォルダのパスを定義した列挙クラスです。
    /// WITH_CODEは、「部署コード.csv」という命名規則でcsvが小分けになるファイルを表しています。
    /// </summary>
    internal class HandyFile
    {

        public string path { get; set; }

        public bool isDirectory { get; set; }

        private HandyFile baseFile;

        public HandyFile(string path) : this(path, false){ }

        public HandyFile(string path, bool isDirectory)
        {
            this.path = path;
            this.isDirectory = isDirectory;
        }

        /// <summary>
        /// 一時ファイル用のコンストラクタです。
        /// </summary>
        /// <param name="path"></param>
        /// <param name="baseFile"></param>
        public HandyFile(string path, HandyFile baseFile) : this(path, false)
        {
            this.baseFile = baseFile;
        }

        /// <summary>
        /// FileStreamを返します。
        /// このメソッドは基本的にファイルにアクセスするファサードの中で呼ばれるため、
        /// 直接クライアントを実装する際に呼び出すことはありません。
        /// </summary>
        /// <param name="fileMode"></param>
        /// <returns></returns>
        public  Stream getFileStream(FileMode fileMode)
        {
            // 親のディレクトリが存在しない場合は生成します。
            if (!this.isDirectory)
            {
                int index = this.path.LastIndexOf("\\");
                string filePath = this.path.Substring(0, index);
                Directory.CreateDirectory(filePath);
            }

            return new FileStream(this.path, fileMode);
        }

        /// <summary>
        /// HandyFile配下の「部署コード.csv」のファイルを生成します。
        /// このメソッドはhasMultipleCsv==trueであるHandyFileでのみ利用可能です。
        /// </summary>
        /// <param name="busyocode"></param>
        /// <returns></returns>
        public HandyFile create(string busyocode)
        {
            if (!this.isDirectory)
            {
                throw new ApplicationException("HadnyFiles.create(string)が利用できないHandyFileに対して呼ばれました。");
            }
            return new HandyFile(string.Format("{0}\\{1}.csv", this.path, busyocode));
        }

        /// <summary>
        /// ファイルを削除します。
        /// ディレクトリの場合は、配下のファイルを全て削除します。
        /// </summary>
        public void delete()
        {
            string filePath = this.path;

            if (this.isDirectory)
            {
                if (Directory.Exists(this.path))
                {
                    Directory.Delete(filePath, true);
                }
            }
            else
            {
                if (File.Exists(filePath))
                {
                    File.Delete(filePath);
                }
            }
        }

        /// <summary>
        /// ファイルが存在するかどうかをチェックします。
        /// </summary>
        /// <returns></returns>
        public bool exists()
        {
            return File.Exists(this.path);
        }

        /// <summary>
        /// ディレクトリの場合、子にフォルダ、あるいはファイルが存在するかをチェックします。
        /// </summary>
        /// <returns></returns>
        public bool existsChildren()
        {
            if (!this.isDirectory)
            {
                throw new ApplicationException("ディレクトリではありません。");
            }

            if (Directory.Exists(this.path))
            {

                string[] files = Directory.GetFiles(this.path);
                if (files == null || files.Count() > 0)
                {
                    return true;
                }
                
            }
            return false;

        }

        /// <summary>
        /// 一時ファイルのパスを生成します。
        /// ファイルの完全性を保証する為、ファイルを一時保存に書き込んでから
        /// リネームすることで対応します。
        /// </summary>
        /// <returns></returns>
        public HandyFile createTmp()
        {

            if (this.isDirectory)
            {
                throw new ApplicationException("HadnyFiles.createTmp)は、ディレクトリに対して利用することは出来ません。" + this.path);
            }
            return new HandyFile(string.Format("{0}.tmp", this.path), this);
        }

        /// <summary>
        /// 一時ファイルのファイル名を元のファイル名にします。
        /// すでに存在する場合は削除してから書き込みます。
        /// </summary>
        public void replaceTmpFile()
        {
            // 一時ファイルであるかどうか判定
            if (baseFile == null)
            {
                throw new ApplicationException("このHandyFileは、一時ファイルではありません。\n path=" + this.path);
            }

            // 一時ファイルが出力されていない場合エラーです。
            if (!exists())
            {
                throw new ApplicationException("一時ファイルの出力が完了していません。\n path=" + this.path);
            }
            else
            {
                // すでにbaseFileが存在するならば削除する
                if (baseFile.exists())
                {
                    baseFile.delete();
                }
                File.Move(this.path, baseFile.path);
            }
            
        }
    }
}
